package org.imraniqbal.pacman;

import java.io.IOException;
import java.util.Arrays;

import org.imraniqbal.engine.Direction;
import org.imraniqbal.engine.Game;
import org.imraniqbal.engine.GameEvent;
import org.imraniqbal.engine.Memory;
import org.imraniqbal.engine.GameController.Controls;
import org.imraniqbal.engine.Map;

/**
 * @author  imran
 */
public class PacmanGame extends Game {
	private static final long serialVersionUID = 8497908691098303103L;
	private static final int NUM_GHOSTS = 4;
	/**
	 * @uml.property  name="pillsLeft"
	 */
	private int pillsLeft;
	/**
	 * @uml.property  name="pacman"
	 * @uml.associationEnd  
	 */
	private Pacman pacman;
	/**
	 * @uml.property  name="ghosts"
	 * @uml.associationEnd  multiplicity="(0 -1)"
	 */
	private Ghost[] ghosts;
	/**
	 * Creates a new pacman Game
	 * @author imran
	 */
	public PacmanGame(){
		super();
		start();
	}
	/**
	 * Initiates new pacman  game, places pills where needed, Ghosts in ghost spawn, Pacman at start location
	 * And adds all game listenners
	 * @author imran
	 */
	@Override
	public void start() {
		setPillsLeft(0);
		this.setMap(new Map("maps/pacman/map.txt"));
		
		pacman = new Pacman(1,1,Direction.LEFT,3);
		pacman.spawn(this.getMap());
		addListener(pacman);
		
		ghosts = new Ghost[NUM_GHOSTS];
		for(int i = 0; i < NUM_GHOSTS; i++){
			ghosts[i] = new Ghost(1,1,i+1);
			ghosts[i].setNumOflives(-1); // set to -1 so they never die
			ghosts[i].spawn(this.getMap());
			addListener(ghosts[i]);
		}
		
		BigPill bigPill = new BigPill(1,1); //add big pills
		getMap().addMappable(bigPill);
		bigPill = new BigPill(18,1);
		getMap().addMappable(bigPill);
		bigPill = new BigPill(1,9);
		getMap().addMappable(bigPill);
		bigPill = new BigPill(18,9);
		getMap().addMappable(bigPill);
		
		//add little pills
		for(int x = 0; x < this.getMap().getX(); x++)
			for(int y = 0; y < this.getMap().getY(); y++){
				if( this.getMap().isEmpty(x, y)){
					LittlePill littPill = new LittlePill(x, y);
					this.getMap().addMappable(littPill);
					setPillsLeft(getPillsLeft() + 1);
				}
			}

	}
	/**
	 * @return  Remaining little pills
	 * @author  imran
	 * @uml.property  name="pillsLeft"
	 */
	public int getPillsLeft() {
		return pillsLeft;
	}
	/**
	 * Sets the number of pills left to number provided
	 * @param pillsLeft  new number of pills
	 * @uml.property  name="pillsLeft"
	 */
	public void setPillsLeft(int pillsLeft) {
		this.pillsLeft = pillsLeft;
	}
	/**
	 * Checks to see if game has ended
	 */
	@Override
	public boolean hasEnded() {
		return (!(pacman.getNumOflives() > 0 && getPillsLeft() > 0));
	}
	/**
	 * Makes game update based on input
	 * @author imran
	 * @throws IOException 
	 */
	@Override
	public void getControl(Controls control, Memory<? extends Game> m) {
		if(hasEnded()){ return; }
		try {
			m.addGameState(this);
		} catch (IOException e) {
			e.printStackTrace();
		}
		switch(control){
			case DOWN:
				pacman.setDirection(Direction.DOWN);
				break;
			case LEFT:
				pacman.setDirection(Direction.LEFT);
				break;
			case RIGHT:
				pacman.setDirection(Direction.RIGHT);
				break;
			case UP:
				pacman.setDirection(Direction.UP);
				break;
			case ACTION:
				return; // we dont anything to do with action
		}
		pacman.updateLocation(getMap());
		for( Ghost g : ghosts){
			g.moveGhost(pacman, getMap());
		}
		notify(new GameEvent(this));

	}

	public Pacman getPacman() {
		return pacman;
	}
	public void setPacman(Pacman pacman) {
		this.pacman = pacman;
	}
	public Ghost[] getGhosts() {
		return ghosts;
	}
	public void setGhosts(Ghost[] ghosts) {
		this.ghosts = ghosts;
	}
	@Override
	public boolean equals(Object obj){
		if(!(obj instanceof PacmanGame)){ return false; }
		return (super.equals(obj) &&
				((PacmanGame)obj).getPacman() == this.getPacman() &&
				((PacmanGame)obj).getPillsLeft() == this.getPillsLeft() &&
				Arrays.equals(((PacmanGame)obj).getGhosts() , this.getGhosts()));
	}
}
